package upgrade

import (
	"context"
	"fmt"
	"os"
	"strconv"
	"time"

	"github.com/influxdata/influxdb/v2"
	"github.com/influxdata/influxdb/v2/cmd/internal"
	"github.com/tcnksm/go-input"
)

func setupAdmin(ctx context.Context, v2 *influxDBv2, req *influxdb.OnboardingRequest) (*influxdb.OnboardingResults, error) {
	res, err := v2.onboardSvc.OnboardInitialUser(ctx, req)

	if err != nil {
		return nil, fmt.Errorf("onboarding error: %w", err)
	}
	return res, nil
}

func isInteractive() bool {
	return !options.force ||
		options.target.userName == "" ||
		options.target.password == "" ||
		options.target.orgName == "" ||
		options.target.bucket == ""
}

func onboardingRequest() (*influxdb.OnboardingRequest, error) {
	if isInteractive() {
		return interactive()
	}
	return nonInteractive()
}

func nonInteractive() (*influxdb.OnboardingRequest, error) {
	if len(options.target.password) < internal.MinPasswordLen {
		return nil, internal.ErrPasswordIsTooShort
	}
	req := &influxdb.OnboardingRequest{
		User:            options.target.userName,
		Password:        options.target.password,
		Token:           options.target.token,
		Org:             options.target.orgName,
		Bucket:          options.target.bucket,
		RetentionPeriod: influxdb.InfiniteRetention,
	}

	dur, err := internal.RawDurationToTimeDuration(options.target.retention)
	if err != nil {
		return nil, err
	}
	if dur > 0 {
		req.RetentionPeriod = uint(dur / time.Hour)
	}
	return req, nil
}

func interactive() (req *influxdb.OnboardingRequest, err error) {
	ui := &input.UI{
		Writer: os.Stdout,
		Reader: os.Stdin,
	}
	req = new(influxdb.OnboardingRequest)
	fmt.Println(string(internal.PromptWithColor(`Welcome to InfluxDB 2.0 upgrade!`, internal.ColorYellow)))
	if options.target.userName != "" {
		req.User = options.target.userName
	} else {
		req.User = internal.GetInput(ui, "Please type your primary username", "")
	}
	if options.target.password != "" && len(options.target.password) >= internal.MinPasswordLen {
		req.Password = options.target.password
	} else {
		req.Password = internal.GetPassword(ui, false)
	}
	if options.target.token != "" {
		req.Token = options.target.token
		// else auto-generated by service
	}
	if options.target.orgName != "" {
		req.Org = options.target.orgName
	} else {
		req.Org = internal.GetInput(ui, "Please type your primary organization name", "")
	}
	if options.target.bucket != "" {
		req.Bucket = options.target.bucket
	} else {
		req.Bucket = internal.GetInput(ui, "Please type your primary bucket name", "")
	}

	dur, err := internal.RawDurationToTimeDuration(options.target.retention)
	if err != nil {
		return nil, err
	}

	if dur > 0 {
		req.RetentionPeriod = uint(dur / time.Hour)
	} else {
		for {
			rpStr := internal.GetInput(ui, "Please type your retention period in hours.\r\nOr press ENTER for infinite.", strconv.Itoa(influxdb.InfiniteRetention))
			rp, err := strconv.Atoi(rpStr)
			if rp >= 0 && err == nil {
				req.RetentionPeriod = uint(rp) * uint(time.Hour)
				break
			}
		}
	}

	if !options.force {
		if confirmed := internal.GetConfirm(ui, func() string {
			rp := "infinite"
			if req.RetentionPeriod > 0 {
				rp = fmt.Sprintf("%d hrs", time.Duration(req.RetentionPeriod)/time.Hour)
			}
			return fmt.Sprintf(`
You have entered:
  Username:          %s
  Organization:      %s
  Bucket:            %s
  Retention Period:  %s
`, req.User, req.Org, req.Bucket, rp)
		}); !confirmed {
			return nil, fmt.Errorf("setup was canceled")
		}
	}

	return req, nil
}
